package org.msi.bayesiannetwork;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: czareq
 * Date: 05.06.11
 * Time: 15:48
 * To change this template use File | Settings | File Templates.
 */
public class MarkovBlanket {

    /**
     * <p>Represents all parents for Node</p>
     */
    private List<String> parents = new ArrayList<String >();

    /**
     * <p>Represents all children for node</p>
     */
    private List<String> children = new ArrayList<String >();

     /**
     * <p>Represents all children's Parents for node</p>
     */
    private List<String> blanket = new ArrayList<String >();

    /**
     * <p>Represents node Variable for markov blanket</p>
     */
    String nodeVariable = new String();

    /**
     *  <p>Creates new instance of {@link MarkovBlanket} class, with specified nodeVariable.</p>
     * @param nodeVariable  the Variable of node
     */
    public MarkovBlanket(String nodeVariable){
        this.nodeVariable = nodeVariable;
    }

    /**
     * <p>Find ad set all parents for containing node Variable</p>
     * @param bn Bayesian Network for searching
     */
    public void findParents (BayesianNetwork bn){
        Map<Integer, List<Integer>> edges = new HashMap<Integer, List<Integer>>();
        edges = bn.getEdges();

        List<String> variables = new ArrayList<String >();
        variables = bn.getVariableList();
        int Id = -1;

        try{
        Id = bn.getNodeByVariableName(nodeVariable).getId();
        }
        catch(NodeNotFoundException exc){
        }

        for(int i=0; i<edges.size(); ++i){
            if(edges.get(i) != null){
                if(edges.get(i).contains(Id)){
                    parents.add(variables.get(i));
                }
            }
        }
    }
    /**
     * <p>Find ad set all children for containing node Variable</p>
     * @param bn Bayesian Network for searching
     */
    public void findChildren (BayesianNetwork bn){
        String guard = "GGG";

               Map<Integer, List<Integer>> edges = new HashMap<Integer, List<Integer>>();
               edges = bn.getEdges();

               List<String> variables = new ArrayList<String >();
               variables = bn.getVariableList();
               int Id = -1;

               try{
               Id = bn.getNodeByVariableName(nodeVariable).getId();
               }
               catch(NodeNotFoundException exc){
               }

               if(edges.containsKey(Id)){
                   for(int i=0; i<edges.get(Id).size(); ++i ){
                       if(!variables.get(edges.get(Id).get(i)).equals(guard))
                           children.add(variables.get(edges.get(Id).get(i)));
                   }
               }
    }

    /**
     * <p>Find and set all markov blanket for containing node Variable</p>
     * @param bn Bayesian Network for searching
     * @return String containing all markov blanket nodes
     */
    public String findMarkovBlanket(BayesianNetwork bn){
        String result = new String();

        parents.clear();
        children.clear();

        findParents(bn);
        findChildren(bn);

        blanket.add(nodeVariable);
        blanket.addAll(parents);
        blanket.addAll(children);

        for (int i=0; i<children.size(); i++){ /*find parents for each children*/
          parents.clear();
          nodeVariable = children.get(i);
          findParents(bn);
          for (int j=0; j<parents.size(); ++j){
            if(!blanket.contains(parents.get(j))){
                blanket.add(parents.get(j));
            }
          }
        }

        for (int j=0; j<blanket.size(); ++j){
            result+=blanket.get(j);
            result+=" ";
        }

         return result;

    }
}
